1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package javax.swing;
26
27 import sun.swing.SwingUtilities2;
28
29 import java.awt.*;
30 import java.awt.event.*;
31 import java.lang.reflect.*;
32 import java.net.*;
33 import java.util.*;
34 import java.io.*;
35 import java.util.*;
36
37 import javax.swing.plaf.*;
38 import javax.swing.text.*;
39 import javax.swing.event.*;
40 import javax.swing.text.html.*;
41 import javax.accessibility.*;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192 public class JEditorPane extends JTextComponent {
193
194
195
196
197
198 public JEditorPane() {
199 super();
200 setFocusCycleRoot(true);
201 setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
202 public Component getComponentAfter(Container focusCycleRoot,
203 Component aComponent) {
204 if (focusCycleRoot != JEditorPane.this ||
205 (!isEditable() && getComponentCount() > 0)) {
206 return super.getComponentAfter(focusCycleRoot,
207 aComponent);
208 } else {
209 Container rootAncestor = getFocusCycleRootAncestor();
210 return (rootAncestor != null)
211 ? rootAncestor.getFocusTraversalPolicy().
212 getComponentAfter(rootAncestor,
213 JEditorPane.this)
214 : null;
215 }
216 }
217 public Component getComponentBefore(Container focusCycleRoot,
218 Component aComponent) {
219 if (focusCycleRoot != JEditorPane.this ||
220 (!isEditable() && getComponentCount() > 0)) {
221 return super.getComponentBefore(focusCycleRoot,
222 aComponent);
223 } else {
224 Container rootAncestor = getFocusCycleRootAncestor();
225 return (rootAncestor != null)
226 ? rootAncestor.getFocusTraversalPolicy().
227 getComponentBefore(rootAncestor,
228 JEditorPane.this)
229 : null;
230 }
231 }
232 public Component getDefaultComponent(Container focusCycleRoot)
233 {
234 return (focusCycleRoot != JEditorPane.this ||
235 (!isEditable() && getComponentCount() > 0))
236 ? super.getDefaultComponent(focusCycleRoot)
237 : null;
238 }
239 protected boolean accept(Component aComponent) {
240 return (aComponent != JEditorPane.this)
241 ? super.accept(aComponent)
242 : false;
243 }
244 });
245 LookAndFeel.installProperty(this,
246 "focusTraversalKeysForward",
247 JComponent.
248 getManagingFocusForwardTraversalKeys());
249 LookAndFeel.installProperty(this,
250 "focusTraversalKeysBackward",
251 JComponent.
252 getManagingFocusBackwardTraversalKeys());
253 }
254
255
256
257
258
259
260
261
262 public JEditorPane(URL initialPage) throws IOException {
263 this();
264 setPage(initialPage);
265 }
266
267
268
269
270
271
272
273
274
275 public JEditorPane(String url) throws IOException {
276 this();
277 setPage(url);
278 }
279
280
281
282
283
284
285
286
287
288
289
290 public JEditorPane(String type, String text) {
291 this();
292 setContentType(type);
293 setText(text);
294 }
295
296
297
298
299
300
301
302 public synchronized void addHyperlinkListener(HyperlinkListener listener) {
303 listenerList.add(HyperlinkListener.class, listener);
304 }
305
306
307
308
309
310
311 public synchronized void removeHyperlinkListener(HyperlinkListener listener) {
312 listenerList.remove(HyperlinkListener.class, listener);
313 }
314
315
316
317
318
319
320
321
322
323 public synchronized HyperlinkListener[] getHyperlinkListeners() {
324 return listenerList.getListeners(javax.swing.event.HyperlinkListener.class);
325 }
326
327
328
329
330
331
332
333
334
335
336
337
338 public void fireHyperlinkUpdate(HyperlinkEvent e) {
339
340 Object[] listeners = listenerList.getListenerList();
341
342
343 for (int i = listeners.length-2; i>=0; i-=2) {
344 if (listeners[i]==HyperlinkListener.class) {
345 ((HyperlinkListener)listeners[i+1]).hyperlinkUpdate(e);
346 }
347 }
348 }
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416 public void setPage(URL page) throws IOException {
417 if (page == null) {
418 throw new IOException("invalid url");
419 }
420 URL loaded = getPage();
421
422
423
424 if (!page.equals(loaded) && page.getRef() == null) {
425 scrollRectToVisible(new Rectangle(0,0,1,1));
426 }
427 boolean reloaded = false;
428 Object postData = getPostData();
429 if ((loaded == null) || !loaded.sameFile(page) || (postData != null)) {
430
431
432 int p = getAsynchronousLoadPriority(getDocument());
433 if (p < 0) {
434
435 InputStream in = getStream(page);
436 if (kit != null) {
437 Document doc = initializeModel(kit, page);
438
439
440
441
442
443 p = getAsynchronousLoadPriority(doc);
444 if (p >= 0) {
445
446 setDocument(doc);
447 synchronized(this) {
448 pageLoader = new PageLoader(doc, in, loaded, page);
449 pageLoader.execute();
450 }
451 return;
452 }
453 read(in, doc);
454 setDocument(doc);
455 reloaded = true;
456 }
457 } else {
458
459 if (pageLoader != null) {
460 pageLoader.cancel(true);
461 }
462
463
464
465 pageLoader = new PageLoader(null, null, loaded, page);
466 pageLoader.execute();
467 return;
468 }
469 }
470 final String reference = page.getRef();
471 if (reference != null) {
472 if (!reloaded) {
473 scrollToReference(reference);
474 }
475 else {
476
477 SwingUtilities.invokeLater(new Runnable() {
478 public void run() {
479 scrollToReference(reference);
480 }
481 });
482 }
483 getDocument().putProperty(Document.StreamDescriptionProperty, page);
484 }
485 firePropertyChange("page", loaded, page);
486 }
487
488
489
490
491 private Document initializeModel(EditorKit kit, URL page) {
492 Document doc = kit.createDefaultDocument();
493 if (pageProperties != null) {
494
495
496 for (Enumeration<String> e = pageProperties.keys(); e.hasMoreElements() ;) {
497 String key = e.nextElement();
498 doc.putProperty(key, pageProperties.get(key));
499 }
500 pageProperties.clear();
501 }
502 if (doc.getProperty(Document.StreamDescriptionProperty) == null) {
503 doc.putProperty(Document.StreamDescriptionProperty, page);
504 }
505 return doc;
506 }
507
508
509
510
511 private int getAsynchronousLoadPriority(Document doc) {
512 return (doc instanceof AbstractDocument ?
513 ((AbstractDocument) doc).getAsynchronousLoadPriority() : -1);
514 }
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531 public void read(InputStream in, Object desc) throws IOException {
532
533 if (desc instanceof HTMLDocument &&
534 kit instanceof HTMLEditorKit) {
535 HTMLDocument hdoc = (HTMLDocument) desc;
536 setDocument(hdoc);
537 read(in, hdoc);
538 } else {
539 String charset = (String) getClientProperty("charset");
540 Reader r = (charset != null) ? new InputStreamReader(in, charset) :
541 new InputStreamReader(in);
542 super.read(r, desc);
543 }
544 }
545
546
547
548
549
550
551
552
553
554
555
556
557
558 void read(InputStream in, Document doc) throws IOException {
559 if (! Boolean.TRUE.equals(doc.getProperty("IgnoreCharsetDirective"))) {
560 final int READ_LIMIT = 1024 * 10;
561 in = new BufferedInputStream(in, READ_LIMIT);
562 in.mark(READ_LIMIT);
563 }
564 try {
565 String charset = (String) getClientProperty("charset");
566 Reader r = (charset != null) ? new InputStreamReader(in, charset) :
567 new InputStreamReader(in);
568 kit.read(r, doc, 0);
569 } catch (BadLocationException e) {
570 throw new IOException(e.getMessage());
571 } catch (ChangedCharSetException changedCharSetException) {
572 String charSetSpec = changedCharSetException.getCharSetSpec();
573 if (changedCharSetException.keyEqualsCharSet()) {
574 putClientProperty("charset", charSetSpec);
575 } else {
576 setCharsetFromContentTypeParameters(charSetSpec);
577 }
578 try {
579 in.reset();
580 } catch (IOException exception) {
581
582 in.close();
583 URL url = (URL)doc.getProperty(Document.StreamDescriptionProperty);
584 if (url != null) {
585 URLConnection conn = url.openConnection();
586 in = conn.getInputStream();
587 } else {
588
589 throw changedCharSetException;
590 }
591 }
592 try {
593 doc.remove(0, doc.getLength());
594 } catch (BadLocationException e) {}
595 doc.putProperty("IgnoreCharsetDirective", Boolean.valueOf(true));
596 read(in, doc);
597 }
598 }
599
600
601
602
603
604 class PageLoader extends SwingWorker<URL, Object> {
605
606
607
608
609 PageLoader(Document doc, InputStream in, URL old, URL page) {
610 this.in = in;
611 this.old = old;
612 this.page = page;
613 this.doc = doc;
614 }
615
616
617
618
619
620
621 protected URL doInBackground() {
622 boolean pageLoaded = false;
623 try {
624 if (in == null) {
625 in = getStream(page);
626 if (kit == null) {
627
628 UIManager.getLookAndFeel().
629 provideErrorFeedback(JEditorPane.this);
630 return old;
631 }
632 }
633
634 if (doc == null) {
635 try {
636 SwingUtilities.invokeAndWait(new Runnable() {
637 public void run() {
638 doc = initializeModel(kit, page);
639 setDocument(doc);
640 }
641 });
642 } catch (InvocationTargetException ex) {
643 UIManager.getLookAndFeel().provideErrorFeedback(
644 JEditorPane.this);
645 return old;
646 } catch (InterruptedException ex) {
647 UIManager.getLookAndFeel().provideErrorFeedback(
648 JEditorPane.this);
649 return old;
650 }
651 }
652
653 read(in, doc);
654 URL page = (URL) doc.getProperty(Document.StreamDescriptionProperty);
655 String reference = page.getRef();
656 if (reference != null) {
657
658
659
660 Runnable callScrollToReference = new Runnable() {
661 public void run() {
662 URL u = (URL) getDocument().getProperty
663 (Document.StreamDescriptionProperty);
664 String ref = u.getRef();
665 scrollToReference(ref);
666 }
667 };
668 SwingUtilities.invokeLater(callScrollToReference);
669 }
670 pageLoaded = true;
671 } catch (IOException ioe) {
672 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
673 } finally {
674 if (pageLoaded) {
675 SwingUtilities.invokeLater(new Runnable() {
676 public void run() {
677 JEditorPane.this.firePropertyChange("page", old, page);
678 }
679 });
680 }
681 return (pageLoaded ? page : old);
682 }
683 }
684
685
686
687
688 InputStream in;
689
690
691
692
693 URL old;
694
695
696
697
698 URL page;
699
700
701
702
703
704
705 Document doc;
706 }
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727 protected InputStream getStream(URL page) throws IOException {
728 final URLConnection conn = page.openConnection();
729 if (conn instanceof HttpURLConnection) {
730 HttpURLConnection hconn = (HttpURLConnection) conn;
731 hconn.setInstanceFollowRedirects(false);
732 Object postData = getPostData();
733 if (postData != null) {
734 handlePostData(hconn, postData);
735 }
736 int response = hconn.getResponseCode();
737 boolean redirect = (response >= 300 && response <= 399);
738
739
740
741
742
743 if (redirect) {
744 String loc = conn.getHeaderField("Location");
745 if (loc.startsWith("http", 0)) {
746 page = new URL(loc);
747 } else {
748 page = new URL(page, loc);
749 }
750 return getStream(page);
751 }
752 }
753
754
755
756 if (SwingUtilities.isEventDispatchThread()) {
757 handleConnectionProperties(conn);
758 } else {
759 try {
760 SwingUtilities.invokeAndWait(new Runnable() {
761 public void run() {
762 handleConnectionProperties(conn);
763 }
764 });
765 } catch (InterruptedException e) {
766 throw new RuntimeException(e);
767 } catch (InvocationTargetException e) {
768 throw new RuntimeException(e);
769 }
770 }
771 return conn.getInputStream();
772 }
773
774
775
776
777 private void handleConnectionProperties(URLConnection conn) {
778 if (pageProperties == null) {
779 pageProperties = new Hashtable<String, Object>();
780 }
781 String type = conn.getContentType();
782 if (type != null) {
783 setContentType(type);
784 pageProperties.put("content-type", type);
785 }
786 pageProperties.put(Document.StreamDescriptionProperty, conn.getURL());
787 String enc = conn.getContentEncoding();
788 if (enc != null) {
789 pageProperties.put("content-encoding", enc);
790 }
791 }
792
793 private Object getPostData() {
794 return getDocument().getProperty(PostDataProperty);
795 }
796
797 private void handlePostData(HttpURLConnection conn, Object postData)
798 throws IOException {
799 conn.setDoOutput(true);
800 DataOutputStream os = null;
801 try {
802 conn.setRequestProperty("Content-Type",
803 "application/x-www-form-urlencoded");
804 os = new DataOutputStream(conn.getOutputStream());
805 os.writeBytes((String) postData);
806 } finally {
807 if (os != null) {
808 os.close();
809 }
810 }
811 }
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829 public void scrollToReference(String reference) {
830 Document d = getDocument();
831 if (d instanceof HTMLDocument) {
832 HTMLDocument doc = (HTMLDocument) d;
833 HTMLDocument.Iterator iter = doc.getIterator(HTML.Tag.A);
834 for (; iter.isValid(); iter.next()) {
835 AttributeSet a = iter.getAttributes();
836 String nm = (String) a.getAttribute(HTML.Attribute.NAME);
837 if ((nm != null) && nm.equals(reference)) {
838
839 try {
840 int pos = iter.getStartOffset();
841 Rectangle r = modelToView(pos);
842 if (r != null) {
843
844
845 Rectangle vis = getVisibleRect();
846
847 r.height = vis.height;
848 scrollRectToVisible(r);
849 setCaretPosition(pos);
850 }
851 } catch (BadLocationException ble) {
852 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
853 }
854 }
855 }
856 }
857 }
858
859
860
861
862
863
864
865
866
867 public URL getPage() {
868 return (URL) getDocument().getProperty(Document.StreamDescriptionProperty);
869 }
870
871
872
873
874
875
876
877
878 public void setPage(String url) throws IOException {
879 if (url == null) {
880 throw new IOException("invalid url");
881 }
882 URL page = new URL(url);
883 setPage(page);
884 }
885
886
887
888
889
890
891
892
893 public String getUIClassID() {
894 return uiClassID;
895 }
896
897
898
899
900
901
902
903 protected EditorKit createDefaultEditorKit() {
904 return new PlainEditorKit();
905 }
906
907
908
909
910
911
912
913
914 public EditorKit getEditorKit() {
915 if (kit == null) {
916 kit = createDefaultEditorKit();
917 isUserSetEditorKit = false;
918 }
919 return kit;
920 }
921
922
923
924
925
926
927
928
929
930 public final String getContentType() {
931 return (kit != null) ? kit.getContentType() : null;
932 }
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963 public final void setContentType(String type) {
964
965
966
967 int parm = type.indexOf(";");
968 if (parm > -1) {
969
970 String paramList = type.substring(parm);
971
972 type = type.substring(0, parm).trim();
973 if (type.toLowerCase().startsWith("text/")) {
974 setCharsetFromContentTypeParameters(paramList);
975 }
976 }
977 if ((kit == null) || (! type.equals(kit.getContentType()))
978 || !isUserSetEditorKit) {
979 EditorKit k = getEditorKitForContentType(type);
980 if (k != null && k != kit) {
981 setEditorKit(k);
982 isUserSetEditorKit = false;
983 }
984 }
985
986 }
987
988
989
990
991
992 private void setCharsetFromContentTypeParameters(String paramlist) {
993 String charset;
994 try {
995
996 int semi = paramlist.indexOf(';');
997 if (semi > -1 && semi < paramlist.length()-1) {
998 paramlist = paramlist.substring(semi + 1);
999 }
1000
1001 if (paramlist.length() > 0) {
1002
1003
1004 HeaderParser hdrParser = new HeaderParser(paramlist);
1005 charset = hdrParser.findValue("charset");
1006 if (charset != null) {
1007 putClientProperty("charset", charset);
1008 }
1009 }
1010 }
1011 catch (IndexOutOfBoundsException e) {
1012
1013 }
1014 catch (NullPointerException e) {
1015
1016 }
1017 catch (Exception e) {
1018
1019 System.err.println("JEditorPane.getCharsetFromContentTypeParameters failed on: " + paramlist);
1020 e.printStackTrace();
1021 }
1022 }
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049 public void setEditorKit(EditorKit kit) {
1050 EditorKit old = this.kit;
1051 isUserSetEditorKit = true;
1052 if (old != null) {
1053 old.deinstall(this);
1054 }
1055 this.kit = kit;
1056 if (this.kit != null) {
1057 this.kit.install(this);
1058 setDocument(this.kit.createDefaultDocument());
1059 }
1060 firePropertyChange("editorKit", old, kit);
1061 }
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082 public EditorKit getEditorKitForContentType(String type) {
1083 if (typeHandlers == null) {
1084 typeHandlers = new Hashtable<String, EditorKit>(3);
1085 }
1086 EditorKit k = typeHandlers.get(type);
1087 if (k == null) {
1088 k = createEditorKitForContentType(type);
1089 if (k != null) {
1090 setEditorKitForContentType(type, k);
1091 }
1092 }
1093 if (k == null) {
1094 k = createDefaultEditorKit();
1095 }
1096 return k;
1097 }
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108 public void setEditorKitForContentType(String type, EditorKit k) {
1109 if (typeHandlers == null) {
1110 typeHandlers = new Hashtable<String, EditorKit>(3);
1111 }
1112 typeHandlers.put(type, k);
1113 }
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128 @Override
1129 public void replaceSelection(String content) {
1130 if (! isEditable()) {
1131 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
1132 return;
1133 }
1134 EditorKit kit = getEditorKit();
1135 if(kit instanceof StyledEditorKit) {
1136 try {
1137 Document doc = getDocument();
1138 Caret caret = getCaret();
1139 boolean composedTextSaved = saveComposedText(caret.getDot());
1140 int p0 = Math.min(caret.getDot(), caret.getMark());
1141 int p1 = Math.max(caret.getDot(), caret.getMark());
1142 if (doc instanceof AbstractDocument) {
1143 ((AbstractDocument)doc).replace(p0, p1 - p0, content,
1144 ((StyledEditorKit)kit).getInputAttributes());
1145 }
1146 else {
1147 if (p0 != p1) {
1148 doc.remove(p0, p1 - p0);
1149 }
1150 if (content != null && content.length() > 0) {
1151 doc.insertString(p0, content, ((StyledEditorKit)kit).
1152 getInputAttributes());
1153 }
1154 }
1155 if (composedTextSaved) {
1156 restoreComposedText();
1157 }
1158 } catch (BadLocationException e) {
1159 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
1160 }
1161 }
1162 else {
1163 super.replaceSelection(content);
1164 }
1165 }
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184 public static EditorKit createEditorKitForContentType(String type) {
1185 Hashtable<String, EditorKit> kitRegistry = getKitRegisty();
1186 EditorKit k = kitRegistry.get(type);
1187 if (k == null) {
1188
1189 String classname = getKitTypeRegistry().get(type);
1190 ClassLoader loader = getKitLoaderRegistry().get(type);
1191 try {
1192 Class c;
1193 if (loader != null) {
1194 c = loader.loadClass(classname);
1195 } else {
1196
1197
1198 c = Class.forName(classname, true, Thread.currentThread().
1199 getContextClassLoader());
1200 }
1201 k = (EditorKit) c.newInstance();
1202 kitRegistry.put(type, k);
1203 } catch (Throwable e) {
1204 k = null;
1205 }
1206 }
1207
1208
1209
1210 if (k != null) {
1211 return (EditorKit) k.clone();
1212 }
1213 return null;
1214 }
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228 public static void registerEditorKitForContentType(String type, String classname) {
1229 registerEditorKitForContentType(type, classname,Thread.currentThread().
1230 getContextClassLoader());
1231 }
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245 public static void registerEditorKitForContentType(String type, String classname, ClassLoader loader) {
1246 getKitTypeRegistry().put(type, classname);
1247 getKitLoaderRegistry().put(type, loader);
1248 getKitRegisty().remove(type);
1249 }
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259 public static String getEditorKitClassNameForContentType(String type) {
1260 return getKitTypeRegistry().get(type);
1261 }
1262
1263 private static Hashtable<String, String> getKitTypeRegistry() {
1264 loadDefaultKitsIfNecessary();
1265 return (Hashtable)SwingUtilities.appContextGet(kitTypeRegistryKey);
1266 }
1267
1268 private static Hashtable<String, ClassLoader> getKitLoaderRegistry() {
1269 loadDefaultKitsIfNecessary();
1270 return (Hashtable)SwingUtilities.appContextGet(kitLoaderRegistryKey);
1271 }
1272
1273 private static Hashtable<String, EditorKit> getKitRegisty() {
1274 Hashtable ht = (Hashtable)SwingUtilities.appContextGet(kitRegistryKey);
1275 if (ht == null) {
1276 ht = new Hashtable(3);
1277 SwingUtilities.appContextPut(kitRegistryKey, ht);
1278 }
1279 return ht;
1280 }
1281
1282
1283
1284
1285
1286
1287
1288 private static void loadDefaultKitsIfNecessary() {
1289 if (SwingUtilities.appContextGet(kitTypeRegistryKey) == null) {
1290 synchronized(defaultEditorKitMap) {
1291 if (defaultEditorKitMap.size() == 0) {
1292 defaultEditorKitMap.put("text/plain",
1293 "javax.swing.JEditorPane$PlainEditorKit");
1294 defaultEditorKitMap.put("text/html",
1295 "javax.swing.text.html.HTMLEditorKit");
1296 defaultEditorKitMap.put("text/rtf",
1297 "javax.swing.text.rtf.RTFEditorKit");
1298 defaultEditorKitMap.put("application/rtf",
1299 "javax.swing.text.rtf.RTFEditorKit");
1300 }
1301 }
1302 Hashtable ht = new Hashtable();
1303 SwingUtilities.appContextPut(kitTypeRegistryKey, ht);
1304 ht = new Hashtable();
1305 SwingUtilities.appContextPut(kitLoaderRegistryKey, ht);
1306 for (String key : defaultEditorKitMap.keySet()) {
1307 registerEditorKitForContentType(key,defaultEditorKitMap.get(key));
1308 }
1309
1310 }
1311 }
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331 public Dimension getPreferredSize() {
1332 Dimension d = super.getPreferredSize();
1333 Container parent = SwingUtilities.getUnwrappedParent(this);
1334 if (parent instanceof JViewport) {
1335 JViewport port = (JViewport) parent;
1336 TextUI ui = getUI();
1337 int prefWidth = d.width;
1338 int prefHeight = d.height;
1339 if (! getScrollableTracksViewportWidth()) {
1340 int w = port.getWidth();
1341 Dimension min = ui.getMinimumSize(this);
1342 if (w != 0 && w < min.width) {
1343
1344 prefWidth = min.width;
1345 }
1346 }
1347 if (! getScrollableTracksViewportHeight()) {
1348 int h = port.getHeight();
1349 Dimension min = ui.getMinimumSize(this);
1350 if (h != 0 && h < min.height) {
1351
1352 prefHeight = min.height;
1353 }
1354 }
1355 if (prefWidth != d.width || prefHeight != d.height) {
1356 d = new Dimension(prefWidth, prefHeight);
1357 }
1358 }
1359 return d;
1360 }
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406 public void setText(String t) {
1407 try {
1408 Document doc = getDocument();
1409 doc.remove(0, doc.getLength());
1410 if (t == null || t.equals("")) {
1411 return;
1412 }
1413 Reader r = new StringReader(t);
1414 EditorKit kit = getEditorKit();
1415 kit.read(r, doc, 0);
1416 } catch (IOException ioe) {
1417 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
1418 } catch (BadLocationException ble) {
1419 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
1420 }
1421 }
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434 public String getText() {
1435 String txt;
1436 try {
1437 StringWriter buf = new StringWriter();
1438 write(buf);
1439 txt = buf.toString();
1440 } catch (IOException ioe) {
1441 txt = null;
1442 }
1443 return txt;
1444 }
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455 public boolean getScrollableTracksViewportWidth() {
1456 Container parent = SwingUtilities.getUnwrappedParent(this);
1457 if (parent instanceof JViewport) {
1458 JViewport port = (JViewport) parent;
1459 TextUI ui = getUI();
1460 int w = port.getWidth();
1461 Dimension min = ui.getMinimumSize(this);
1462 Dimension max = ui.getMaximumSize(this);
1463 if ((w >= min.width) && (w <= max.width)) {
1464 return true;
1465 }
1466 }
1467 return false;
1468 }
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478 public boolean getScrollableTracksViewportHeight() {
1479 Container parent = SwingUtilities.getUnwrappedParent(this);
1480 if (parent instanceof JViewport) {
1481 JViewport port = (JViewport) parent;
1482 TextUI ui = getUI();
1483 int h = port.getHeight();
1484 Dimension min = ui.getMinimumSize(this);
1485 if (h >= min.height) {
1486 Dimension max = ui.getMaximumSize(this);
1487 if (h <= max.height) {
1488 return true;
1489 }
1490 }
1491 }
1492 return false;
1493 }
1494
1495
1496
1497
1498
1499
1500
1501
1502 private void writeObject(ObjectOutputStream s) throws IOException {
1503 s.defaultWriteObject();
1504 if (getUIClassID().equals(uiClassID)) {
1505 byte count = JComponent.getWriteObjCounter(this);
1506 JComponent.setWriteObjCounter(this, --count);
1507 if (count == 0 && ui != null) {
1508 ui.installUI(this);
1509 }
1510 }
1511 }
1512
1513
1514
1515 private SwingWorker<URL, Object> pageLoader;
1516
1517
1518
1519
1520 private EditorKit kit;
1521 private boolean isUserSetEditorKit;
1522
1523 private Hashtable<String, Object> pageProperties;
1524
1525
1526 final static String PostDataProperty = "javax.swing.JEditorPane.postdata";
1527
1528
1529
1530
1531 private Hashtable<String, EditorKit> typeHandlers;
1532
1533
1534
1535
1536 private static final Object kitRegistryKey =
1537 new StringBuffer("JEditorPane.kitRegistry");
1538 private static final Object kitTypeRegistryKey =
1539 new StringBuffer("JEditorPane.kitTypeRegistry");
1540 private static final Object kitLoaderRegistryKey =
1541 new StringBuffer("JEditorPane.kitLoaderRegistry");
1542
1543
1544
1545
1546
1547 private static final String uiClassID = "EditorPaneUI";
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561 public static final String W3C_LENGTH_UNITS = "JEditorPane.w3cLengthUnits";
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575 public static final String HONOR_DISPLAY_PROPERTIES = "JEditorPane.honorDisplayProperties";
1576
1577 static final Map<String, String> defaultEditorKitMap = new HashMap<String, String>(0);
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589 protected String paramString() {
1590 String kitString = (kit != null ?
1591 kit.toString() : "");
1592 String typeHandlersString = (typeHandlers != null ?
1593 typeHandlers.toString() : "");
1594
1595 return super.paramString() +
1596 ",kit=" + kitString +
1597 ",typeHandlers=" + typeHandlersString;
1598 }
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615 public AccessibleContext getAccessibleContext() {
1616 if (getEditorKit() instanceof HTMLEditorKit) {
1617 if (accessibleContext == null || accessibleContext.getClass() !=
1618 AccessibleJEditorPaneHTML.class) {
1619 accessibleContext = new AccessibleJEditorPaneHTML();
1620 }
1621 } else if (accessibleContext == null || accessibleContext.getClass() !=
1622 AccessibleJEditorPane.class) {
1623 accessibleContext = new AccessibleJEditorPane();
1624 }
1625 return accessibleContext;
1626 }
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643 protected class AccessibleJEditorPane extends AccessibleJTextComponent {
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655 public String getAccessibleDescription() {
1656 String description = accessibleDescription;
1657
1658
1659 if (description == null) {
1660 description = (String)getClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY);
1661 }
1662 if (description == null) {
1663 description = JEditorPane.this.getContentType();
1664 }
1665 return description;
1666 }
1667
1668
1669
1670
1671
1672
1673
1674
1675 public AccessibleStateSet getAccessibleStateSet() {
1676 AccessibleStateSet states = super.getAccessibleStateSet();
1677 states.add(AccessibleState.MULTI_LINE);
1678 return states;
1679 }
1680 }
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697 protected class AccessibleJEditorPaneHTML extends AccessibleJEditorPane {
1698
1699 private AccessibleContext accessibleContext;
1700
1701 public AccessibleText getAccessibleText() {
1702 return new JEditorPaneAccessibleHypertextSupport();
1703 }
1704
1705 protected AccessibleJEditorPaneHTML () {
1706 HTMLEditorKit kit = (HTMLEditorKit)JEditorPane.this.getEditorKit();
1707 accessibleContext = kit.getAccessibleContext();
1708 }
1709
1710
1711
1712
1713
1714
1715 public int getAccessibleChildrenCount() {
1716 if (accessibleContext != null) {
1717 return accessibleContext.getAccessibleChildrenCount();
1718 } else {
1719 return 0;
1720 }
1721 }
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733 public Accessible getAccessibleChild(int i) {
1734 if (accessibleContext != null) {
1735 return accessibleContext.getAccessibleChild(i);
1736 } else {
1737 return null;
1738 }
1739 }
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749 public Accessible getAccessibleAt(Point p) {
1750 if (accessibleContext != null && p != null) {
1751 try {
1752 AccessibleComponent acomp =
1753 accessibleContext.getAccessibleComponent();
1754 if (acomp != null) {
1755 return acomp.getAccessibleAt(p);
1756 } else {
1757 return null;
1758 }
1759 } catch (IllegalComponentStateException e) {
1760 return null;
1761 }
1762 } else {
1763 return null;
1764 }
1765 }
1766 }
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777 protected class JEditorPaneAccessibleHypertextSupport
1778 extends AccessibleJEditorPane implements AccessibleHypertext {
1779
1780 public class HTMLLink extends AccessibleHyperlink {
1781 Element element;
1782
1783 public HTMLLink(Element e) {
1784 element = e;
1785 }
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795 public boolean isValid() {
1796 return JEditorPaneAccessibleHypertextSupport.this.linksValid;
1797 }
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807 public int getAccessibleActionCount() {
1808 return 1;
1809 }
1810
1811
1812
1813
1814
1815
1816
1817
1818 public boolean doAccessibleAction(int i) {
1819 if (i == 0 && isValid() == true) {
1820 URL u = (URL) getAccessibleActionObject(i);
1821 if (u != null) {
1822 HyperlinkEvent linkEvent =
1823 new HyperlinkEvent(JEditorPane.this, HyperlinkEvent.EventType.ACTIVATED, u);
1824 JEditorPane.this.fireHyperlinkUpdate(linkEvent);
1825 return true;
1826 }
1827 }
1828 return false;
1829 }
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841 public String getAccessibleActionDescription(int i) {
1842 if (i == 0 && isValid() == true) {
1843 Document d = JEditorPane.this.getDocument();
1844 if (d != null) {
1845 try {
1846 return d.getText(getStartIndex(),
1847 getEndIndex() - getStartIndex());
1848 } catch (BadLocationException exception) {
1849 return null;
1850 }
1851 }
1852 }
1853 return null;
1854 }
1855
1856
1857
1858
1859
1860
1861
1862
1863 public Object getAccessibleActionObject(int i) {
1864 if (i == 0 && isValid() == true) {
1865 AttributeSet as = element.getAttributes();
1866 AttributeSet anchor =
1867 (AttributeSet) as.getAttribute(HTML.Tag.A);
1868 String href = (anchor != null) ?
1869 (String) anchor.getAttribute(HTML.Attribute.HREF) : null;
1870 if (href != null) {
1871 URL u;
1872 try {
1873 u = new URL(JEditorPane.this.getPage(), href);
1874 } catch (MalformedURLException m) {
1875 u = null;
1876 }
1877 return u;
1878 }
1879 }
1880 return null;
1881 }
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898 public Object getAccessibleActionAnchor(int i) {
1899 return getAccessibleActionDescription(i);
1900 }
1901
1902
1903
1904
1905
1906
1907
1908
1909 public int getStartIndex() {
1910 return element.getStartOffset();
1911 }
1912
1913
1914
1915
1916
1917
1918
1919 public int getEndIndex() {
1920 return element.getEndOffset();
1921 }
1922 }
1923
1924 private class LinkVector extends Vector<HTMLLink> {
1925 public int baseElementIndex(Element e) {
1926 HTMLLink l;
1927 for (int i = 0; i < elementCount; i++) {
1928 l = elementAt(i);
1929 if (l.element == e) {
1930 return i;
1931 }
1932 }
1933 return -1;
1934 }
1935 }
1936
1937 LinkVector hyperlinks;
1938 boolean linksValid = false;
1939
1940
1941
1942
1943 private void buildLinkTable() {
1944 hyperlinks.removeAllElements();
1945 Document d = JEditorPane.this.getDocument();
1946 if (d != null) {
1947 ElementIterator ei = new ElementIterator(d);
1948 Element e;
1949 AttributeSet as;
1950 AttributeSet anchor;
1951 String href;
1952 while ((e = ei.next()) != null) {
1953 if (e.isLeaf()) {
1954 as = e.getAttributes();
1955 anchor = (AttributeSet) as.getAttribute(HTML.Tag.A);
1956 href = (anchor != null) ?
1957 (String) anchor.getAttribute(HTML.Attribute.HREF) : null;
1958 if (href != null) {
1959 hyperlinks.addElement(new HTMLLink(e));
1960 }
1961 }
1962 }
1963 }
1964 linksValid = true;
1965 }
1966
1967
1968
1969
1970 public JEditorPaneAccessibleHypertextSupport() {
1971 hyperlinks = new LinkVector();
1972 Document d = JEditorPane.this.getDocument();
1973 if (d != null) {
1974 d.addDocumentListener(new DocumentListener() {
1975 public void changedUpdate(DocumentEvent theEvent) {
1976 linksValid = false;
1977 }
1978 public void insertUpdate(DocumentEvent theEvent) {
1979 linksValid = false;
1980 }
1981 public void removeUpdate(DocumentEvent theEvent) {
1982 linksValid = false;
1983 }
1984 });
1985 }
1986 }
1987
1988
1989
1990
1991
1992
1993 public int getLinkCount() {
1994 if (linksValid == false) {
1995 buildLinkTable();
1996 }
1997 return hyperlinks.size();
1998 }
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008 public int getLinkIndex(int charIndex) {
2009 if (linksValid == false) {
2010 buildLinkTable();
2011 }
2012 Element e = null;
2013 Document doc = JEditorPane.this.getDocument();
2014 if (doc != null) {
2015 for (e = doc.getDefaultRootElement(); ! e.isLeaf(); ) {
2016 int index = e.getElementIndex(charIndex);
2017 e = e.getElement(index);
2018 }
2019 }
2020
2021
2022
2023
2024 return hyperlinks.baseElementIndex(e);
2025 }
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035 public AccessibleHyperlink getLink(int linkIndex) {
2036 if (linksValid == false) {
2037 buildLinkTable();
2038 }
2039 if (linkIndex >= 0 && linkIndex < hyperlinks.size()) {
2040 return hyperlinks.elementAt(linkIndex);
2041 } else {
2042 return null;
2043 }
2044 }
2045
2046
2047
2048
2049
2050
2051
2052
2053 public String getLinkText(int linkIndex) {
2054 if (linksValid == false) {
2055 buildLinkTable();
2056 }
2057 Element e = (Element) hyperlinks.elementAt(linkIndex);
2058 if (e != null) {
2059 Document d = JEditorPane.this.getDocument();
2060 if (d != null) {
2061 try {
2062 return d.getText(e.getStartOffset(),
2063 e.getEndOffset() - e.getStartOffset());
2064 } catch (BadLocationException exception) {
2065 return null;
2066 }
2067 }
2068 }
2069 return null;
2070 }
2071 }
2072
2073 static class PlainEditorKit extends DefaultEditorKit implements ViewFactory {
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083 public ViewFactory getViewFactory() {
2084 return this;
2085 }
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095 public View create(Element elem) {
2096 Document doc = elem.getDocument();
2097 Object i18nFlag
2098 = doc.getProperty("i18n");
2099 if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) {
2100
2101 return createI18N(elem);
2102 } else {
2103 return new WrappedPlainView(elem);
2104 }
2105 }
2106
2107 View createI18N(Element elem) {
2108 String kind = elem.getName();
2109 if (kind != null) {
2110 if (kind.equals(AbstractDocument.ContentElementName)) {
2111 return new PlainParagraph(elem);
2112 } else if (kind.equals(AbstractDocument.ParagraphElementName)){
2113 return new BoxView(elem, View.Y_AXIS);
2114 }
2115 }
2116 return null;
2117 }
2118
2119
2120
2121
2122
2123 static class PlainParagraph extends javax.swing.text.ParagraphView {
2124
2125 PlainParagraph(Element elem) {
2126 super(elem);
2127 layoutPool = new LogicalView(elem);
2128 layoutPool.setParent(this);
2129 }
2130
2131 protected void setPropertiesFromAttributes() {
2132 Component c = getContainer();
2133 if ((c != null)
2134 && (! c.getComponentOrientation().isLeftToRight()))
2135 {
2136 setJustification(StyleConstants.ALIGN_RIGHT);
2137 } else {
2138 setJustification(StyleConstants.ALIGN_LEFT);
2139 }
2140 }
2141
2142
2143
2144
2145
2146 public int getFlowSpan(int index) {
2147 Component c = getContainer();
2148 if (c instanceof JTextArea) {
2149 JTextArea area = (JTextArea) c;
2150 if (! area.getLineWrap()) {
2151
2152 return Integer.MAX_VALUE;
2153 }
2154 }
2155 return super.getFlowSpan(index);
2156 }
2157
2158 protected SizeRequirements calculateMinorAxisRequirements(int axis,
2159 SizeRequirements r)
2160 {
2161 SizeRequirements req
2162 = super.calculateMinorAxisRequirements(axis, r);
2163 Component c = getContainer();
2164 if (c instanceof JTextArea) {
2165 JTextArea area = (JTextArea) c;
2166 if (! area.getLineWrap()) {
2167
2168 req.minimum = req.preferred;
2169 }
2170 }
2171 return req;
2172 }
2173
2174
2175
2176
2177
2178
2179
2180
2181 static class LogicalView extends CompositeView {
2182
2183 LogicalView(Element elem) {
2184 super(elem);
2185 }
2186
2187 protected int getViewIndexAtPosition(int pos) {
2188 Element elem = getElement();
2189 if (elem.getElementCount() > 0) {
2190 return elem.getElementIndex(pos);
2191 }
2192 return 0;
2193 }
2194
2195 protected boolean
2196 updateChildren(DocumentEvent.ElementChange ec,
2197 DocumentEvent e, ViewFactory f)
2198 {
2199 return false;
2200 }
2201
2202 protected void loadChildren(ViewFactory f) {
2203 Element elem = getElement();
2204 if (elem.getElementCount() > 0) {
2205 super.loadChildren(f);
2206 } else {
2207 View v = new GlyphView(elem);
2208 append(v);
2209 }
2210 }
2211
2212 public float getPreferredSpan(int axis) {
2213 if( getViewCount() != 1 )
2214 throw new Error("One child view is assumed.");
2215
2216 View v = getView(0);
2217
2218 return v.getPreferredSpan(axis);
2219 }
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236 protected void forwardUpdateToView(View v, DocumentEvent e,
2237 Shape a, ViewFactory f) {
2238 v.setParent(this);
2239 super.forwardUpdateToView(v, e, a, f);
2240 }
2241
2242
2243
2244
2245 public void paint(Graphics g, Shape allocation) {
2246 }
2247
2248 protected boolean isBefore(int x, int y, Rectangle alloc) {
2249 return false;
2250 }
2251
2252 protected boolean isAfter(int x, int y, Rectangle alloc) {
2253 return false;
2254 }
2255
2256 protected View getViewAtPoint(int x, int y, Rectangle alloc) {
2257 return null;
2258 }
2259
2260 protected void childAllocation(int index, Rectangle a) {
2261 }
2262 }
2263 }
2264 }
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285 static class HeaderParser {
2286
2287
2288 String raw;
2289 String[][] tab;
2290
2291 public HeaderParser(String raw) {
2292 this.raw = raw;
2293 tab = new String[10][2];
2294 parse();
2295 }
2296
2297 private void parse() {
2298
2299 if (raw != null) {
2300 raw = raw.trim();
2301 char[] ca = raw.toCharArray();
2302 int beg = 0, end = 0, i = 0;
2303 boolean inKey = true;
2304 boolean inQuote = false;
2305 int len = ca.length;
2306 while (end < len) {
2307 char c = ca[end];
2308 if (c == '=') {
2309 tab[i][0] = new String(ca, beg, end-beg).toLowerCase();
2310 inKey = false;
2311 end++;
2312 beg = end;
2313 } else if (c == '\"') {
2314 if (inQuote) {
2315 tab[i++][1]= new String(ca, beg, end-beg);
2316 inQuote=false;
2317 do {
2318 end++;
2319 } while (end < len && (ca[end] == ' ' || ca[end] == ','));
2320 inKey=true;
2321 beg=end;
2322 } else {
2323 inQuote=true;
2324 end++;
2325 beg=end;
2326 }
2327 } else if (c == ' ' || c == ',') {
2328 if (inQuote) {
2329 end++;
2330 continue;
2331 } else if (inKey) {
2332 tab[i++][0] = (new String(ca, beg, end-beg)).toLowerCase();
2333 } else {
2334 tab[i++][1] = (new String(ca, beg, end-beg));
2335 }
2336 while (end < len && (ca[end] == ' ' || ca[end] == ',')) {
2337 end++;
2338 }
2339 inKey = true;
2340 beg = end;
2341 } else {
2342 end++;
2343 }
2344 }
2345
2346 if (--end > beg) {
2347 if (!inKey) {
2348 if (ca[end] == '\"') {
2349 tab[i++][1] = (new String(ca, beg, end-beg));
2350 } else {
2351 tab[i++][1] = (new String(ca, beg, end-beg+1));
2352 }
2353 } else {
2354 tab[i][0] = (new String(ca, beg, end-beg+1)).toLowerCase();
2355 }
2356 } else if (end == beg) {
2357 if (!inKey) {
2358 if (ca[end] == '\"') {
2359 tab[i++][1] = String.valueOf(ca[end-1]);
2360 } else {
2361 tab[i++][1] = String.valueOf(ca[end]);
2362 }
2363 } else {
2364 tab[i][0] = String.valueOf(ca[end]).toLowerCase();
2365 }
2366 }
2367 }
2368
2369 }
2370
2371 public String findKey(int i) {
2372 if (i < 0 || i > 10)
2373 return null;
2374 return tab[i][0];
2375 }
2376
2377 public String findValue(int i) {
2378 if (i < 0 || i > 10)
2379 return null;
2380 return tab[i][1];
2381 }
2382
2383 public String findValue(String key) {
2384 return findValue(key, null);
2385 }
2386
2387 public String findValue(String k, String Default) {
2388 if (k == null)
2389 return Default;
2390 k = k.toLowerCase();
2391 for (int i = 0; i < 10; ++i) {
2392 if (tab[i][0] == null) {
2393 return Default;
2394 } else if (k.equals(tab[i][0])) {
2395 return tab[i][1];
2396 }
2397 }
2398 return Default;
2399 }
2400
2401 public int findInt(String k, int Default) {
2402 try {
2403 return Integer.parseInt(findValue(k, String.valueOf(Default)));
2404 } catch (Throwable t) {
2405 return Default;
2406 }
2407 }
2408 }
2409
2410 }